
#include "stdio.h"
#include "stdlib.h"
/**
 * 学生成绩结构体
 */
typedef struct student_grade
{
    char no[10];   //学号
    int mathGrade; //数学成绩
    int enGrade;   //英语成绩
    int chGrade;   //语文成绩
    int total;     //总分
    int avg;       //平均分
    int rank;      //排名
} StudentGrade;

/**
 * 学生列表
 */
typedef struct student_list
{
    StudentGrade *arr[10]; //数组 最大10个
    int n;                 //学生数量 小于10
} StudentList;

/**
 * 创建 学生
 * @return
 */
static StudentGrade *createStudentGrade();

/**
 * 释放内存
 * @param grade
 */
static void freeStudentGrade(StudentGrade *grade);

/**
 * 创建列表
 * @return
 */
static StudentList *createStudentList(int n);

/**
 * 释放内存
 * @param studentList
 */
static void freeStudentList(StudentList *studentList);

/**
 * 排序
 * @param studentList
 */
static void sortStudentList(StudentList *studentList);

/**
 * 打印学生成绩列表
 * @param studentList
 */
static void printStudentList(StudentList *studentList);

/**
 * 获取输入数字
 * @param min 最小值
 * @param max 最大值
 * @return
 */
static int getNumFromInput(int min, int max);

/**
 * 输入学生成绩
 * @param grade
 */
static void inputStudentGrade(StudentGrade *grade);

/**
 * 程序入口
 * @return
 */
int main32()
{
    //输入学生人数 1-9
    printf("please input the number of students:\n");
    int n = getNumFromInput(1, 9);
    int i;
    //创建列表
    StudentList *studentList = createStudentList(n);
    for (i = 0; i < n; i++)
    {
        printf("please input the no.%d student's grade\n", i + 1);
        //输入成绩
        inputStudentGrade(studentList->arr[i]);
    }
    //排名
    sortStudentList(studentList);
    //打印
    printStudentList(studentList);
    freeStudentList(studentList);
    return 0;
}

/**
 * 创建
 * @return
 */
static StudentGrade *createStudentGrade()
{
    return (StudentGrade *)calloc(1, sizeof(StudentGrade));
}

/**
 * 释放内存
 * @param grade
 */
static void freeStudentGrade(StudentGrade *grade)
{
    free(grade);
}
/**
 * 创建列表
 * @return
 */
static StudentList *createStudentList(int n)
{
    //分片内存
    StudentList *list = calloc(1, sizeof(StudentList));
    if (n > 10)
    {
        printf("list size must less than 10\n");
        exit(1);
    }
    list->n = n;
    for (int i = 0; i < n; i++)
    {
        //创建学生成绩对象
        list->arr[i] = createStudentGrade();
    }
    return list;
}
/**
 * 排序
 * @param studentList
 */
static void sortStudentList(StudentList *studentList)
{
    StudentGrade *temp;
    //冒泡排序
    for (int i = 0; i < studentList->n; i++)
    {
        for (int j = 0; j < studentList->n - i - 1; j++)
        {
            if (studentList->arr[j]->total < studentList->arr[j + 1]->total)
            {
                temp = studentList->arr[j];
                studentList->arr[j] = studentList->arr[j + 1];
                studentList->arr[j + 1] = temp;
            }
        }
    }
    //设置排名
    int rank = 1;
    studentList->arr[0]->rank = rank++;
    for (int i = 1; i < studentList->n; i++)
    {
        if (studentList->arr[i]->total == studentList->arr[i - 1]->total)
        {
            rank--;
        }
        studentList->arr[i]->rank = rank++;
    }
}

/**
 * 释放内存
 * @param studentList
 */
static void freeStudentList(StudentList *studentList)
{
    for (int i = 0; i < studentList->n; i++)
    {
        //释放学生对象 内存
        freeStudentGrade(studentList->arr[i]);
    }
    //释放列表内存
    free(studentList);
}
/**
 * 获取输入数字
 * @param min 最小值
 * @param max 最大值
 * @return
 */
static int getNumFromInput(int min, int max)
{
    int n;
    int i;
    while (1)
    {
        i = scanf("%d", &n);
        if (i == 1 && getchar() == '\n')
        {
            if (n > max || n < min)
            {
                printf("the number should be %d-%d!\n", min, max);
                continue;
            }
            break;
        }
        else
        {
            printf("please input a number!\n");
        }
        while (1) //清空缓存区
        {
            char c = getchar();
            if (c == '\n')
                break;
        }
    }
    return n;
}

/**
 * 输入学生成绩，格式: 学号 数学 英语 语文
 * @param grade
 */
static void inputStudentGrade(StudentGrade *grade)
{
    scanf("%s %d %d %d", grade->no, &grade->mathGrade, &grade->enGrade, &grade->chGrade);
    grade->total = grade->mathGrade + grade->enGrade + grade->chGrade;
    grade->avg = grade->total / 3;
    printf("no:%s, math:%d, en:%d, ch:%d, total:%d, avg:%d\n", grade->no, grade->mathGrade,
           grade->enGrade, grade->chGrade, grade->total, grade->avg);
}
/**
 * 打印学生成绩列表
 * @param studentList
 */
static void printStudentList(StudentList *studentList)
{
    printf("rank result:\n");
    printf("%4s%10s%5s%5s%5s%10s%5s\n", "rank", "no", "math", "en", "ch", "total", "avg");
    for (int i = 0; i < studentList->n; i++)
    {
        printf("%4d%10s%5d%5d%5d%10d%5d\n",
               studentList->arr[i]->rank,
               studentList->arr[i]->no,
               studentList->arr[i]->mathGrade,
               studentList->arr[i]->enGrade,
               studentList->arr[i]->chGrade,
               studentList->arr[i]->total,
               studentList->arr[i]->avg);
    }
}
